package com.yuzhi.master.sewage.rmstSz.service.Impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yuzhi.common.core.domain.entity.SysDictData;
import com.yuzhi.common.core.domain.PageQuery;
import com.yuzhi.common.core.domain.entity.SysUser;
import com.yuzhi.common.core.page.PageDataInfo;
import com.yuzhi.common.enums.NoticeMsgValEnum;
import com.yuzhi.common.helper.LoginHelper;
import com.yuzhi.master.conBjMx.domain.bo.ConBjMxBo;
import com.yuzhi.master.conBjMx.domain.vo.ConBjMxVo;
import com.yuzhi.master.conBjMx.service.IConBjMxService;
import com.yuzhi.master.drainAlarmRule.domain.bo.DrainAlarmConditionBo;
import com.yuzhi.master.drainAlarmRule.domain.request.DrainAlarmRuleReq;
import com.yuzhi.master.drainAlarmRule.domain.vo.DrainAlarmRuleVo;
import com.yuzhi.master.drainAlarmRule.service.IDrainAlarmRuleService;
import com.yuzhi.master.drainEvents.domain.bo.DrainEventsBo;
import com.yuzhi.master.drainEvents.service.IDrainEventsService;
import com.yuzhi.master.drainMsgNotice.domain.bo.DrainMsgNoticeBo;
import com.yuzhi.master.drainMsgNotice.service.IDrainMsgNoticeService;
import com.yuzhi.master.drainRRmst.domain.vo.DrainRRmstVo;
import com.yuzhi.master.drainSms.service.IDrainSmsInfoService;
import com.yuzhi.master.sewage.rmstSz.entity.DrainRmstSz;
import com.yuzhi.master.sewage.rmstSz.mapper.DrainRmstSzMapper;
import com.yuzhi.master.sewage.rmstSz.service.IAlarmRuleProcessor;
import com.yuzhi.master.drainCorrelation.service.IDrainCorrelationService;
import com.yuzhi.master.drainCorrelation.domain.vo.DrainCorrelationVo;
import com.yuzhi.system.service.ISysDictTypeService;
import com.yuzhi.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.LinkedHashMap;

/**
 * 报警规则处理器
 * 负责处理报警规则的逻辑判断和触发
 */
@Slf4j
@Service
public class AlarmRuleProcessor implements IAlarmRuleProcessor {

    @Autowired
    private IDrainAlarmRuleService drainAlarmRuleService;

    @Autowired
    private ISysDictTypeService dictTypeService;

    @Autowired
    private IConBjMxService iConBjMxService;

    @Autowired
    private IDrainMsgNoticeService drainMsgNoticeService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IDrainCorrelationService iDrainCorrelationService;

    @Autowired
    private IDrainEventsService drainEventsService;

    @Autowired
    private IDrainSmsInfoService idrainSmsInfoService;

    /**
     * 检查报警规则
     * @param drainRmstSz 实时数据
     */
    public List<String> checkAlarmRules(DrainRmstSz drainRmstSz, DrainRRmstVo drainRRmstVo) {
        List<String> alarmMessages = new ArrayList<>();
        try {
            String factId = drainRmstSz.getFactId();
            
            // 1. 先查询设备特定的报警规则
            DrainAlarmRuleReq request = new DrainAlarmRuleReq();
            List<String> facilityTypes = Arrays.asList("4", "5");
            request.setDeviceIds(factId);
            request.setFacilityTypes(facilityTypes); // 污水管网
            // 设置分页查询参数，避免空指针异常
            PageQuery pageQuery = new PageQuery();
            pageQuery.setPageNum(1);
            pageQuery.setPageSize(999); // 设置一个合理的分页大小
            request.setPageQuery(pageQuery);
            
            PageDataInfo pageDataInfo = drainAlarmRuleService.selectPageList(request);
            
            List<DrainAlarmRuleVo> alarmRules = new ArrayList<>();
            
            // 优先从设备特定规则中过滤启用的规则（rule_status=true）
            if (pageDataInfo != null && pageDataInfo.getList() != null && !pageDataInfo.getList().isEmpty()) {
                List<DrainAlarmRuleVo> enabledRules = ((List<DrainAlarmRuleVo>) pageDataInfo.getList())
                        .stream()
                        .filter(rule -> Boolean.TRUE.equals(rule.getRuleStatus()))
                        .collect(Collectors.toList());
                alarmRules.addAll(enabledRules);
            }
            
            // 如果设备特定规则（启用）为空，则查询通用规则（deviceIds = "0"），并同样仅保留启用的规则
            if (alarmRules.isEmpty()) {
                request.setDeviceIds("0");
                pageDataInfo = drainAlarmRuleService.selectPageList(request);
                if (pageDataInfo != null && pageDataInfo.getList() != null && !pageDataInfo.getList().isEmpty()) {
                    List<DrainAlarmRuleVo> enabledRules = ((List<DrainAlarmRuleVo>) pageDataInfo.getList())
                            .stream()
                            .filter(rule -> Boolean.TRUE.equals(rule.getRuleStatus()))
                            .collect(Collectors.toList());
                    alarmRules.addAll(enabledRules);
                }
            }
            
            if (alarmRules.isEmpty()) {
                log.info("设备 {} 没有找到匹配的报警规则", factId);
                return alarmMessages;
            }
            
            // 2. 获取字典数据，用于字段映射
            Map<String, String> fieldMapping = getFieldMapping();
            
            // 3. 检查每个报警规则
            boolean anyTriggered = false;
            for (DrainAlarmRuleVo alarmRule : alarmRules) {
                if (alarmRule.getRuleStatus() != null && !alarmRule.getRuleStatus()) {
                    log.debug("跳过禁用的规则: {}", alarmRule.getId());
                    continue; // 跳过禁用的规则
                }
                
                boolean shouldAlarm = evaluateAlarmConditions(alarmRule, drainRmstSz, fieldMapping);
                log.debug("规则 {} 评估结果: {}, 设备ID: {}", alarmRule.getId(), shouldAlarm, factId);
                
                if (shouldAlarm) {
                    anyTriggered = true;
                    // 触发报警
                    triggerAlarm(alarmRule, drainRmstSz, fieldMapping,drainRRmstVo);
                    // 收集可读的异常信息
                    List<String> perRuleMsgs = buildRuleAlarmMessages(alarmRule, drainRmstSz, fieldMapping, drainRRmstVo);
                    if (perRuleMsgs != null && !perRuleMsgs.isEmpty()) {
                        alarmMessages.addAll(perRuleMsgs);
                    }
                }
            }
            // 若本次数据未触发任何异常报警，则执行报警结束逻辑
            if (!anyTriggered) {
                try {
                    for (DrainAlarmRuleVo rule : alarmRules) {
                        iConBjMxService.updateLatestRecordByFKey(
                                drainRmstSz.getFactId(),
                                rule.getAlarmType(),
                                drainRmstSz.getCjTime(),
                                "3"
                        );
                    }
                } catch (Exception ex) {
                    log.warn("未触发报警时更新最新记录状态失败: deviceId={}, err={}", drainRmstSz.getFactId(), ex.getMessage());
                }
            }
            
        } catch (Exception e) {
            log.error("检查报警规则时发生异常", e);
        }
        return alarmMessages;
    }
    
    /**
     * 获取字段映射关系（字典值 -> 实体字段名）
     * @return 字段映射Map
     */
    private Map<String, String> getFieldMapping() {
        Map<String, String> fieldMapping = new HashMap<>();
        try {
            List<SysDictData> dictDataList = dictTypeService.selectDictDataByType("alarm_rule_type");
            if (dictDataList != null) {
                for (SysDictData dictData : dictDataList) {
                    if (dictData.getRemark() != null && !dictData.getRemark().isEmpty()) {
                        // 使用字典“键值(value)”作为key，映射到“备注(remark)”作为实体字段名
                        fieldMapping.put(dictData.getDictValue(), dictData.getRemark());
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取字段映射失败", e);
        }
        
        // 添加默认映射
        fieldMapping.put("管网cod", "codJs");
        fieldMapping.put("氨氮", "adJs");
        fieldMapping.put("管网充满度", "fullLevel");
        fieldMapping.put("进水流量", "flowInJs");
        fieldMapping.put("液位", "qcYw");
        fieldMapping.put("温度", "jsSw");
        fieldMapping.put("电量", "batPow");
        
        return fieldMapping;
    }
    
    /**
     * 评估报警条件
     * @param alarmRule 报警规则
     * @param drainRmstSz 实时数据
     * @param fieldMapping 字段映射
     * @return 是否应该报警
     */
    private boolean evaluateAlarmConditions(DrainAlarmRuleVo alarmRule, DrainRmstSz drainRmstSz, Map<String, String> fieldMapping) {
        if (alarmRule.getConditions() == null || alarmRule.getConditions().isEmpty()) {
            return false;
        }
        
        // 按条件顺序排序
        List<DrainAlarmConditionBo> sortedConditions = alarmRule.getConditions().stream()
                .sorted(Comparator.comparing(DrainAlarmConditionBo::getItemConditionOrder))
                .collect(Collectors.toList());
        
        boolean result = false;
        String relation = null;
        
        for (int i = 0; i < sortedConditions.size(); i++) {
            DrainAlarmConditionBo condition = sortedConditions.get(i);
            boolean conditionResult = evaluateSingleCondition(condition, drainRmstSz, fieldMapping);
            
            if (i == 0) {
                result = conditionResult;
            } else {
                // 根据关系符计算逻辑结果
                if ("&&".equals(relation)) {
                    result = result && conditionResult;
                } else if ("||".equals(relation)) {
                    result = result || conditionResult;
                } else {
                    result = conditionResult;
                }
            }
            
            relation = condition.getRelation();
        }
        
        return result;
    }
    
    /**
     * 评估单个条件
     * @param condition 条件
     * @param drainRmstSz 实时数据
     * @param fieldMapping 字段映射
     * @return 条件是否满足
     */
    private boolean evaluateSingleCondition(DrainAlarmConditionBo condition, DrainRmstSz drainRmstSz, Map<String, String> fieldMapping) {
        try {
            String monitorItemName = condition.getMonitorItemName();
        
            String operator = condition.getOperator();
            BigDecimal threshold = condition.getThreshold();
            // 特殊处理：当监测项为“9”（管经范围）时，先根据测站ID查询关联关系并按规则的管径范围过滤
            if ("9".equals(String.valueOf(monitorItemName))) {
                String rulePipeRange = condition.getPipeDiameter();
                if (rulePipeRange == null || rulePipeRange.trim().isEmpty()) {
                    log.debug("规则未配置管径范围，跳过该条件。ruleId={}, conditionOrder={}", condition.getRuleId(), condition.getItemConditionOrder());
                    return false;
                }
                DrainCorrelationVo correlation = null;
                try {
                    correlation = iDrainCorrelationService.queryByStcd(drainRmstSz.getFactId());
                } catch (Exception e) {
                    log.warn("根据测站ID查询关联信息失败，跳过该条件。stcd={}", drainRmstSz.getFactId(), e);
                    return false;
                }
                if (correlation == null || correlation.getDraiPipeD1() == null) {
                    log.debug("未获取到测站管径信息，跳过该条件。stcd={}", drainRmstSz.getFactId());
                    return false;
                }
                Integer stationPipeDiameter = correlation.getDraiPipeD1();
                boolean match = isPipeDiameterInRange(stationPipeDiameter, rulePipeRange);
                if (!match) {
                    return false;
                }
                // 若匹配则认为该条件成立（本条件仅作为筛选是否应用该规则项）
                return true;
            }
            
            // 获取对应的实体字段名
            String fieldName = fieldMapping.get(monitorItemName);
            if (fieldName == null) {
                log.warn("未找到监测项 {} 对应的字段映射", monitorItemName);
                return false;
            }
            
            // 获取字段值
            Object fieldValue = getFieldValue(drainRmstSz, fieldName);
            if (fieldValue == null) {
                log.debug("监测项 {} 对应的字段 {} 值为null，设备ID: {}", monitorItemName, fieldName, drainRmstSz.getFactId());
                return false;
            }
            
            // 转换为BigDecimal进行比较
            BigDecimal actualValue = convertToBigDecimal(fieldValue);
            if (actualValue == null) {
                log.debug("监测项 {} 的字段值 {} 无法转换为数值，设备ID: {}", monitorItemName, fieldValue, drainRmstSz.getFactId());
                return false;
            }
            
            // 执行比较操作
            switch (operator) {
                case ">":
                    return actualValue.compareTo(threshold) > 0;
                case ">=":
                    return actualValue.compareTo(threshold) >= 0;
                case "<":
                    return actualValue.compareTo(threshold) < 0;
                case "<=":
                    return actualValue.compareTo(threshold) <= 0;
                case "==":
                case "=":
                    return actualValue.compareTo(threshold) == 0;
                case "!=":
                    return actualValue.compareTo(threshold) != 0;
                default:
                    log.warn("不支持的运算符: {}", operator);
                    return false;
            }
            
        } catch (Exception e) {
            log.error("评估条件时发生异常: {}", condition, e);
            return false;
        }
    }
    
    /**
     * 获取实体字段值
     * @param drainRmstSz 实体对象
     * @param fieldName 字段名
     * @return 字段值
     */
    private Object getFieldValue(DrainRmstSz drainRmstSz, String fieldName) {
        try {
            // 使用反射获取字段值
            java.lang.reflect.Field field = DrainRmstSz.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(drainRmstSz);
        } catch (Exception e) {
            log.error("获取字段 {} 的值时发生异常", fieldName, e);
            return null;
        }
    }
    
    /**
     * 转换为BigDecimal
     * @param value 原始值
     * @return BigDecimal值
     */
    private BigDecimal convertToBigDecimal(Object value) {
        if (value == null) {
            return null;
        }
        
        try {
            if (value instanceof BigDecimal) {
                return (BigDecimal) value;
            } else if (value instanceof String) {
                return new BigDecimal((String) value);
            } else if (value instanceof Number) {
                return new BigDecimal(value.toString());
            } else {
                return new BigDecimal(value.toString());
            }
        } catch (NumberFormatException e) {
            log.warn("无法转换数值: {}", value);
            return null;
        }
    }
    
    /**
     * 触发报警
     * @param alarmRule 报警规则
     * @param drainRmstSz 实时数据
     * @param fieldMapping 字段映射
     */
    private void triggerAlarm(DrainAlarmRuleVo alarmRule, DrainRmstSz drainRmstSz, Map<String, String> fieldMapping,DrainRRmstVo drainRRmstVo) {
        try {
            // 构建JSON格式的报警信息
            String alarmInfoJson = buildAlarmInfoJson(alarmRule, drainRmstSz, fieldMapping);
            // 打印到控制台（实际项目中可以发送到消息队列、邮件、短信等）
            log.warn("报警信息: {}", alarmInfoJson);
            // 将报警信息存储到数据库
            saveAlarmToDatabase(alarmRule, drainRmstSz, fieldMapping, alarmInfoJson,drainRRmstVo);
            
        } catch (Exception e) {
            log.error("触发报警时发生异常", e);
        }
    }


    
    /**
     * 构建JSON格式的报警信息
     * @param alarmRule 报警规则
     * @param drainRmstSz 实时数据
     * @param fieldMapping 字段映射
     * @return JSON格式的报警信息
     */
    private String buildAlarmInfoJson(DrainAlarmRuleVo alarmRule, DrainRmstSz drainRmstSz, Map<String, String> fieldMapping) {
        try {
            StringBuilder jsonBuilder = new StringBuilder();
            jsonBuilder.append("{\n");
            jsonBuilder.append("  \"alert_trigger\": {\n");
            // 设备ID
            jsonBuilder.append("    \"device_id\": \"").append(drainRmstSz.getFactId()).append("\",\n");
            // 报警类型
            jsonBuilder.append("    \"alert_type\": \"").append(getAlarmTypeDesc(alarmRule.getAlarmType())).append("\",\n");
            // 设施类型
            jsonBuilder.append("    \"facility_type\": ").append(alarmRule.getFacilityType()).append(",\n");
            // 接收人员
            jsonBuilder.append("    \"receiver\": \"").append(alarmRule.getReceiverIds()).append("\",\n");
            // 触发时间
            String triggerTime = formatTriggerTime(drainRmstSz.getCjTime());
            jsonBuilder.append("    \"trigger_time\": \"").append(triggerTime).append("\",\n");
            // 规则ID
            jsonBuilder.append("    \"rule_id\": \"").append(alarmRule.getId()).append("\",\n");
            // 触发条件
            jsonBuilder.append("    \"trigger_conditions\": [\n");
            if (alarmRule.getConditions() != null) {
                boolean firstCondition = true;
                for (DrainAlarmConditionBo condition : alarmRule.getConditions()) {
                    // 仅输出满足为真的条件
                    boolean conditionTrue = evaluateSingleCondition(condition, drainRmstSz, fieldMapping);
                    if (conditionTrue) {
                        if (!firstCondition) {
                            jsonBuilder.append(",\n");
                        }
                        firstCondition = false;
                        // 构建条件JSON
                        String fieldName = fieldMapping.get(condition.getMonitorItemName());
                        Object fieldValueObj = fieldName == null ? null : getFieldValue(drainRmstSz, fieldName);
                        BigDecimal actualValue = convertToBigDecimal(fieldValueObj);
                        BigDecimal threshold = condition.getThreshold();
                        BigDecimal diff = (actualValue != null && threshold != null)
                                ? actualValue.subtract(threshold)
                                : null;
                        jsonBuilder.append("      {\n");
                        jsonBuilder.append("        \"parameter\": \"").append(condition.getMonitorItemName()).append("\",\n");
                        jsonBuilder.append("        \"current_value\": ").append(actualValue != null ? actualValue.stripTrailingZeros().toPlainString() : "null").append(",\n");
                        jsonBuilder.append("        \"threshold\": ").append(threshold != null ? threshold.stripTrailingZeros().toPlainString() : "null").append(",\n");
                        jsonBuilder.append("        \"operator\": \"").append(condition.getOperator()).append("\",\n");
                        jsonBuilder.append("        \"difference\": ").append(diff != null ? diff.stripTrailingZeros().toPlainString() : "null");
                        jsonBuilder.append("\n      }");
                    }
                }
            }
            jsonBuilder.append("\n    ]\n");
            jsonBuilder.append("  }\n");
            jsonBuilder.append("}");
            return jsonBuilder.toString();
        } catch (Exception e) {
            log.error("构建JSON格式报警信息时发生异常", e);
            return "{\"error\": \"构建报警信息失败\"}";
        }
    }
    
    /**
     * 格式化触发时间
     * @param cjTime 采集时间
     * @return 格式化的时间字符串
     */
    private String formatTriggerTime(LocalDateTime cjTime) {
        if (cjTime == null) {
            return java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm"));
        }
        try {
            return cjTime.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm"));
        } catch (Exception e) {
            log.warn("时间格式化失败，使用当前时间: {}", e.getMessage());
            return java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm"));
        }
    }
    
    /**
     * 将报警信息保存到数据库
     * @param alarmRule 报警规则
     * @param drainRmstSz 实时数据
     * @param fieldMapping 字段映射
     * @param alarmInfoJson 报警描述信息
     */
    private void saveAlarmToDatabase(DrainAlarmRuleVo alarmRule, DrainRmstSz drainRmstSz, 
                                   Map<String, String> fieldMapping, String alarmInfoJson,DrainRRmstVo drainRRmstVo) {
        try {
            //查询记录表数据是否大于规则时间
            ConBjMxBo bjMxBo = new ConBjMxBo();
            bjMxBo.setFKey(drainRmstSz.getFactId());
            bjMxBo.setBjType(alarmRule.getAlarmType());
            List<ConBjMxVo> conBjMxVoList = iConBjMxService.getfFeyId(bjMxBo);
            // 根据规则的 interval_value/interval_unit 判断是否允许新增
            boolean allowedByInterval = shouldInsertByInterval(conBjMxVoList, alarmRule);
            // 为每个触发的条件创建一条报警记录
            if (alarmRule.getConditions() != null) {
                for (DrainAlarmConditionBo condition : alarmRule.getConditions()) {
                    boolean conditionTrue = evaluateSingleCondition(condition, drainRmstSz, fieldMapping);
                    if (conditionTrue) {
                        // 未达到新增时间间隔时，跳过新增
                        if (!allowedByInterval) {
                            continue;
                        }
                        ConBjMxBo conBjMxBo = new ConBjMxBo();
                        // 设置外键ID（设备ID）
                        conBjMxBo.setFKey(drainRmstSz.getFactId());
                        // 设置外键类型（4：污水管网）
                        conBjMxBo.setFKeyType(Integer.valueOf(alarmRule.getFacilityType()));
                        conBjMxBo.setBjType(alarmRule.getAlarmType());
                        //设置设备id的名称
                        conBjMxBo.setFKeyName(drainRRmstVo.getStnm());
                        // 设置参数ID（从字典中获取，如果没有则使用默认值）
                        Integer bjCsId = getParameterId(condition.getMonitorItemName());
                        conBjMxBo.setBjCsId(bjCsId != null ? bjCsId : 1);
                        // 设置参数名称
                        conBjMxBo.setBjCsName(condition.getMonitorItemName());
                        // 设置参数阈值
                        if (condition.getThreshold() != null) {
                            conBjMxBo.setCsYz(condition.getThreshold().stripTrailingZeros().toPlainString());
                        }
                        // 设置采集值（报警值）
                        String fieldName = fieldMapping.get(condition.getMonitorItemName());
                        Object fieldValueObj = fieldName != null ? getFieldValue(drainRmstSz, fieldName) : null;
                        if (fieldValueObj != null) {
                            conBjMxBo.setCjValue(fieldValueObj.toString());
                        }
                        // 构建简化的触发条件描述
                        String conditionDesc = buildConditionDescription(condition, drainRmstSz, fieldMapping);
                        conBjMxBo.setCbDesc(drainRRmstVo.getStnm()+";"+conditionDesc);
                        // 设置报警异常时间
                        if (drainRmstSz.getCjTime() != null) {
                            conBjMxBo.setCbTime(drainRmstSz.getCjTime());
                        } else {
                            conBjMxBo.setCbTime(java.time.LocalDateTime.now());
                        }
                        // 设置是否处理状态（0：待受理）
                        conBjMxBo.setIsCl("0");
                        // 设置报警设备位置
                        conBjMxBo.setDLg(drainRRmstVo.getStLong().toString()+","+drainRRmstVo.getStLat().toString());
                        conBjMxBo.setAlarmRuleId(alarmRule.getId());
                        conBjMxBo.setTransferWork(alarmRule.getTransferWork());
                        //创建消息通知实体 推送消息通知
                        Map<String,String>  paramMap  = new HashMap<>();
                        DrainMsgNoticeBo perNotice = new DrainMsgNoticeBo();
                        paramMap.put(NoticeMsgValEnum.ALARM_DEVICE_NAME.getMsgType(),drainRRmstVo.getStnm());
                        paramMap.put(NoticeMsgValEnum.ALARM_TIME.getMsgType(), String.valueOf(drainRmstSz.getCjTime()));
                        paramMap.put(NoticeMsgValEnum.ALARM_FACTOR_NAME.getMsgType(),alarmRule.getAlarmType());
                        paramMap.put(NoticeMsgValEnum.WARNING_VALUE.getMsgType(),fieldValueObj.toString());
                        // 保存到数据库
                        try {
                            Boolean result = iConBjMxService.insertByBo(conBjMxBo);
                            DrainEventsBo drainEventsBo  = new DrainEventsBo();
                            String userId = LoginHelper.getUserId();
                            if (alarmRule.getTransferWork() == true){
                                drainEventsBo.setSourceType("4");
                                drainEventsBo.setSiteName(drainRmstSz.getFactId());
                                drainEventsBo.setSourceId(drainRmstSz.getFactId());
                                drainEventsBo.setSiteId(alarmRule.getDeviceIds());
                                drainEventsBo.setSiteType(alarmRule.getFacilityType());
                                drainEventsBo.setDescription(drainRRmstVo.getStnm()+";"+conditionDesc);
                                drainEventsBo.setEventsStatus("2");
                                drainEventsBo.setReporterId(userId);
                                drainEventsBo.setReportedAt(String.valueOf(LocalDateTime.now()));
                                drainEventsBo.setLongitude(drainRRmstVo.getStLong().toString());
                                drainEventsBo.setLatitude(drainRRmstVo.getStLat().toString());
                                drainEventsBo.setStatusType(2);
                                drainEventsService.add(drainEventsBo);
                            }
                            // 检查是否需要发送短信
                            if ("1".equals(alarmRule.getSendMessage())) {
                                try {
                                    // 解析接收人ID列表（逗号分隔）
                                    String receivers = alarmRule.getReceiverIds();
                                    if (receivers != null && !receivers.trim().isEmpty()) {
                                        List<String> allUserIds = Arrays.stream(receivers.split(","))
                                                .map(String::trim)
                                                .filter(id -> !id.isEmpty())
                                                .distinct()
                                                .collect(Collectors.toList());
                                        
                                        if (!allUserIds.isEmpty()) {
                                            // 查询用户信息
                                            List<SysUser> sysUserList = userService.selectUserByIds(allUserIds);
                                            
                                            // 为每个用户发送短信
                                            for (SysUser user : sysUserList) {
                                                if (user.getPhonenumber() != null && !user.getPhonenumber().trim().isEmpty()) {
                                                    // 构建短信内容
                                                    String smsMsg = String.format("【排水管网报警】设备[%s]发生%s报警，请及时处理！", 
                                                            drainRRmstVo.getStnm(), 
                                                            getAlarmTypeDesc(alarmRule.getAlarmType()));
                                                    
                                                    // 构建短信模板参数
                                                    LinkedHashMap<String, String> smsMap = new LinkedHashMap<>();
                                                    smsMap.put("deviceName", drainRRmstVo.getStnm());
                                                    smsMap.put("alarmType", getAlarmTypeDesc(alarmRule.getAlarmType()));
                                                    smsMap.put("alarmTime", formatTriggerTime(drainRmstSz.getCjTime()));
                                                    // 发送短信（使用默认模板ID，可根据实际需要调整）
                                                    String templateId = "SMS_ALARM_TEMPLATE"; // 请根据实际短信模板ID调整
                                                    try {
                                                        idrainSmsInfoService.sendSmsInfo(user.getPhonenumber(), "2", smsMsg, templateId, smsMap);
                                                        log.info("短信发送成功，接收人: {}, 手机号: {}, 设备: {}", 
                                                                user.getUserName(), user.getPhonenumber(), drainRRmstVo.getStnm());
                                                    } catch (Exception smsEx) {
                                                        log.error("短信发送失败，接收人: {}, 手机号: {}, 设备: {}, 错误: {}", 
                                                                user.getUserName(), user.getPhonenumber(), drainRRmstVo.getStnm(), smsEx.getMessage());
                                                    }
                                                } else {
                                                    log.warn("用户 {} 手机号为空，跳过短信发送", user.getUserName());
                                                }
                                            }
                                        } else {
                                            log.warn("解析接收人ID列表为空，设备: {}", drainRRmstVo.getStnm());
                                        }
                                    } else {
                                        log.warn("报警规则未配置接收人，设备: {}", drainRRmstVo.getStnm());
                                    }
                                } catch (Exception e) {
                                    log.error("发送短信时发生异常，设备: {}, 错误: {}", drainRRmstVo.getStnm(), e.getMessage(), e);
                                }
                            }
                            // 消息转发存储记录（支持多个接收人，逗号分隔）
                            String receivers = alarmRule.getReceiverIds();
                            if (receivers != null && !receivers.trim().isEmpty()) {
                                // 规则里“接收人”字段可能已被映射为姓名，这里尝试将姓名批量转换为ID
                                try {
                                    String idCsv = userService.getUserIdsByNames(receivers);
                                    if (idCsv != null && !idCsv.trim().isEmpty()) {
                                        receivers = idCsv;
                                    }
                                } catch (Exception ex) {
                                    log.warn("接收人姓名转ID失败，按原值处理: {}", ex.getMessage());
                                }
                                List<String> receiverIds = Arrays.stream(receivers.split(","))
                                        .map(String::trim)
                                        .filter(id -> !id.isEmpty())
                                        .distinct()
                                        .collect(Collectors.toList());
                                if (!receiverIds.isEmpty()) {
                                    // 批量查询 用户ID -> 用户姓名 映射
                                    Map<String, String> userNameMap = userService.selectUserName(receiverIds);
                                    for (String rid : receiverIds) {
                                        perNotice.setNoticeVal(drainRRmstVo.getStnm()+";"+conditionDesc+",请尽快处理!");
                                        perNotice.setFkId(drainRmstSz.getFactId());
                                        perNotice.setNoticeStatus("0");
                                        perNotice.setFkType("4");
                                        // 针对每个接收人分别记录
                                        perNotice.setNoticeUser(rid);
                                        perNotice.setNoticeUserName(userNameMap != null ? userNameMap.getOrDefault(rid, rid) : rid);
                                        drainMsgNoticeService.sendMsgNotice(perNotice, paramMap);
                                    }
                                } else {
                                    // 没有有效ID，按原逻辑发送一次
                                    drainMsgNoticeService.sendMsgNotice(perNotice, paramMap);
                                }
                            } else {
                                // 无接收人或为空，按原逻辑发送一次
                                drainMsgNoticeService.sendMsgNotice(perNotice, paramMap);
                            }
                            if (result) {
                                log.info("报警信息保存成功，设备ID: {}, 参数: {}", 
                                        drainRmstSz.getFactId(), condition.getMonitorItemName());
                            } else {
                                log.error("报警信息保存失败，设备ID: {}, 参数: {}", 
                                        drainRmstSz.getFactId(), condition.getMonitorItemName());
                            }
                        } catch (Exception e) {
                            log.error("保存报警信息时发生异常，设备ID: {}, 参数: {}", 
                                    drainRmstSz.getFactId(), condition.getMonitorItemName(), e);
                        }
                    }
                }
            }
            
        } catch (Exception e) {
            log.error("构建报警数据对象时发生异常", e);
        }
    }

    /**
     * 为单条规则构建可读的异常信息列表（仅包含满足的条件）
     */
    private List<String> buildRuleAlarmMessages(DrainAlarmRuleVo alarmRule, DrainRmstSz drainRmstSz,
                                                Map<String, String> fieldMapping, DrainRRmstVo drainRRmstVo) {
        List<String> messages = new ArrayList<>();
        try {
            if (alarmRule.getConditions() == null || alarmRule.getConditions().isEmpty()) {
                return messages;
            }
            for (DrainAlarmConditionBo condition : alarmRule.getConditions()) {
                boolean conditionTrue = evaluateSingleCondition(condition, drainRmstSz, fieldMapping);
                if (conditionTrue) {
                    String desc = buildConditionDescription(condition, drainRmstSz, fieldMapping);
                    String msg = String.format("设备[%s]%s 规则[%s] 触发: %s",
                            drainRmstSz.getFactId(),
                            drainRRmstVo != null && drainRRmstVo.getStnm() != null ? "(" + drainRRmstVo.getStnm() + ")" : "",
                            alarmRule.getId(),
                            desc);
                    messages.add(msg);
                }
            }
        } catch (Exception e) {
            log.warn("构建规则报警消息失败: {}", e.getMessage());
        }
        return messages;
    }
    
    /**
     * 构建简化的触发条件描述
     * @param condition 报警条件
     * @param drainRmstSz 实时数据
     * @param fieldMapping 字段映射
     * @return 简化的条件描述
     */
    private String buildConditionDescription(DrainAlarmConditionBo condition, DrainRmstSz drainRmstSz,
                                          Map<String, String> fieldMapping) {
        try {
            StringBuilder desc = new StringBuilder();
            
            // 获取字段值
            String fieldName = fieldMapping.get(condition.getMonitorItemName());
            Object fieldValueObj = fieldName != null ? getFieldValue(drainRmstSz, fieldName) : null;
            BigDecimal actualValue = convertToBigDecimal(fieldValueObj);
            BigDecimal threshold = condition.getThreshold();
            
            // 计算差值
            BigDecimal diff = (actualValue != null && threshold != null)
                    ? actualValue.subtract(threshold)
                    : null;
            
            // 构建描述：监测项名称 当前值: 实际值 规则条件: 运算符 阈值 差值: 差值
            desc.append(condition.getMonitorItemName())
                .append(" 当前值: ")
                .append(actualValue != null ? actualValue.stripTrailingZeros().toPlainString() : "-")
                .append(" 规则条件: ")
                .append(condition.getOperator())
                .append(" ")
                .append(threshold != null ? threshold.stripTrailingZeros().toPlainString() : "-")
                .append(" 差值: ")
                .append(diff != null ? diff.stripTrailingZeros().toPlainString() : "-");
            
            return desc.toString();
            
        } catch (Exception e) {
            log.error("构建条件描述时发生异常", e);
            return "条件描述构建失败";
        }
    }
    
    /**
     * 根据监测项名称获取参数ID
     * @param monitorItemName 监测项名称
     * @return 参数ID
     */
    private Integer getParameterId(String monitorItemName) {
        try {
            // 从字典中获取参数ID
            List<SysDictData> dictDataList = dictTypeService.selectDictDataByType("alarm_rule_type");
            if (dictDataList != null) {
                for (SysDictData dictData : dictDataList) {
                    if (monitorItemName.equals(dictData.getDictLabel())) {
                        // 如果字典值可以转换为数字，则使用该值作为参数ID
                        try {
                            return Integer.parseInt(dictData.getDictValue());
                        } catch (NumberFormatException e) {
                            // 如果转换失败，继续查找
                            continue;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("获取参数ID时发生异常", e);
        }
        
        // 默认参数ID映射
        Map<String, Integer> defaultParamIds = new HashMap<>();
        defaultParamIds.put("管网cod", 1);
        defaultParamIds.put("氨氮", 2);
        defaultParamIds.put("管网充满度", 3);
        defaultParamIds.put("进水流量", 4);
        defaultParamIds.put("液位", 5);
        defaultParamIds.put("温度", 6);
        defaultParamIds.put("电量", 7);
        
        return defaultParamIds.getOrDefault(monitorItemName, 1);
    }
    
    /**
     * 获取报警类型描述
     * @param alarmType 报警类型
     * @return 描述
     */
    private String getAlarmTypeDesc(String alarmType) {
        switch (alarmType) {
            case "1": return "离线报警";
            case "2": return "液位异常";
            case "3": return "水质检测报警";
            case "4": return "流速报警";
            case "5": return "充满度报警";
            default: return "未知类型";
        }
    }

    /**
     * 判断是否满足规则间隔要求以允许新增记录
     * 优先规则：
     * 1) 无历史记录 -> 允许
     * 2) intervalUnit 为空或 intervalValue 为空 -> 允许
     * 3) intervalUnit 包含“采集即触发” -> 允许
     * 4) 按“小时/分钟”等单位计算是否超过间隔
     */
    @Override
    public boolean shouldInsertByInterval(List<ConBjMxVo> historyList, DrainAlarmRuleVo alarmRule) {
        try {
            // 没有历史记录，直接允许
            if (historyList == null || historyList.isEmpty()) {
                return true;
            }
            Integer intervalValue = alarmRule.getIntervalValue();
            String intervalUnit = alarmRule.getIntervalUnit();
            if (intervalValue == null || intervalUnit == null || intervalUnit.trim().isEmpty()) {
                return true;
            }
            String unit = intervalUnit.trim();
            if (unit.contains("采集即触发")) {
                return true;
            }
            // 取最新的一条（按cbTime最大）并检查is_cl状态
            LocalDateTime lastTime = null;
            String lastIsCl = null;
            for (ConBjMxVo vo : historyList) {
                if (vo.getCbTime() != null) {
                    if (lastTime == null || vo.getCbTime().isAfter(lastTime)) {
                        lastTime = vo.getCbTime();
                        lastIsCl = vo.getIsCl(); // 记录最新记录的is_cl值
                    }
                }
            }
            // 没有有效的cb_time，允许
            if (lastTime == null) {
                return true;
            }
            // 检查最新记录的is_cl状态：0、1、2时不允许新增
            if (lastIsCl != null && (lastIsCl.equals("0") || lastIsCl.equals("1")  || lastIsCl.equals("2") )) {
                log.info("最新报警记录状态为{}，不允许新增报警记录", lastIsCl);
                return false;
            }
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime nextAllowed;
            // 小时
            if (unit.contains("小时") || unit.equalsIgnoreCase("hour") || unit.equalsIgnoreCase("hours") || unit.equalsIgnoreCase("h")) {
                nextAllowed = lastTime.plusHours(intervalValue.longValue());
            } else if (unit.contains("分钟") || unit.equalsIgnoreCase("minute") || unit.equalsIgnoreCase("minutes") || unit.equalsIgnoreCase("min") || unit.equalsIgnoreCase("m")) {
                nextAllowed = lastTime.plusMinutes(intervalValue.longValue());
            } else if (unit.contains("天") || unit.equalsIgnoreCase("day") || unit.equalsIgnoreCase("days") || unit.equalsIgnoreCase("d")) {
                nextAllowed = lastTime.plusDays(intervalValue.longValue());
            } else {
                // 未知单位，默认放行
                return true;
            }
            return !now.isBefore(nextAllowed); // now >= nextAllowed -> 允许
        } catch (Exception e) {
            log.warn("间隔校验异常，默认允许新增: {}", e.getMessage());
            return true;
        }
    }

    /**
     * 判断实际管径是否命中规则范围表达式
     * 固定优先范围：200-300、350-450、500-900、≥1000（支持 ">=1000" 写法）
     * 其余情况回退到通用解析以兼容历史数据
     */
    private boolean isPipeDiameterInRange(Integer actualDiameter, String rangeExpr) {
        if (actualDiameter == null || rangeExpr == null) {
            return false;
        }
        String expr = rangeExpr.trim().replaceAll("\\s+", "");

        // 固定范围优先判断
        if ("200-300".equals(expr)) {
            return actualDiameter >= 200 && actualDiameter <= 300;
        }
        if ("350-450".equals(expr)) {
            return actualDiameter >= 350 && actualDiameter <= 450;
        }
        if ("500-900".equals(expr)) {
            return actualDiameter >= 500 && actualDiameter <= 900;
        }
        if ("≥1000".equals(expr) || ">=1000".equals(expr)) {
            return actualDiameter >= 1000;
        }
        // 区间表达式：a-b
        if (expr.contains("-")) {
            String[] parts = expr.split("-");
            if (parts.length == 2) {
                try {
                    int min = Integer.parseInt(parts[0]);
                    int max = Integer.parseInt(parts[1]);
                    return actualDiameter >= min && actualDiameter <= max;
                } catch (NumberFormatException ignore) {
                    return false;
                }
            }
            return false;
        }
        // 前缀比较
        if (expr.startsWith(">=" ) || expr.startsWith("≥")) {
            String numStr = expr.startsWith("≥") ? expr.substring(1) : expr.substring(2);
            try {
                int val = Integer.parseInt(numStr);
                return actualDiameter >= val;
            } catch (NumberFormatException ignore) { return false; }
        }
        if (expr.startsWith("<=" ) || expr.startsWith("≤")) {
            String numStr = expr.startsWith("≤") ? expr.substring(1) : expr.substring(2);
            try {
                int val = Integer.parseInt(numStr);
                return actualDiameter <= val;
            } catch (NumberFormatException ignore) { return false; }
        }
        if (expr.startsWith(">")) {
            try {
                int val = Integer.parseInt(expr.substring(1));
                return actualDiameter > val;
            } catch (NumberFormatException ignore) { return false; }
        }
        if (expr.startsWith("<")) {
            try {
                int val = Integer.parseInt(expr.substring(1));
                return actualDiameter < val;
            } catch (NumberFormatException ignore) { return false; }
        }
        // 纯数字：等于
        try {
            int val = Integer.parseInt(expr);
            return actualDiameter == val;
        } catch (NumberFormatException ignore) {
            return false;
        }
    }
}
